import { isArray, isEmpty, isFunction, isObject, isString } from "@/utils"
import {
    GetanTableColumnProps,
    GetanTableProps,
    GetanTableSummaryColumnProps,
    GetanTableSummaryProps,
    GetanTableSummaryTitleProps,
    SummaryFunction
} from "../types"

/**
 * 支持统计，本地统计 & 远程统计，后台字段：summary
 */
export function useSummary(props: Ref<Partial<GetanTableProps>>, columns: Ref<GetanTableColumnProps[]>, showColumns: Ref<Recordable[]>) {
    /**
     * 后端返回统计数据
     */
    const summaryData = ref<Recordable>({})
    /**
     * 使用列定义配置需要统计的列
     */
    const summaryColumns = computed(() => columns.value.filter(v => v.summary))

    const summaryFunction = (tableData: Recordable[]) => {
        const { summary } = unref(props)
        if (isArray(summary)) {
            return (summary as GetanTableSummaryProps[]).map(v => parseSummary(v, tableData, showColumns))
        } else if (isObject(summary)) {
            return parseSummary(summary as GetanTableSummaryProps, tableData, showColumns)
        } else if (!isEmpty(summaryColumns.value)) {
            const config: Recordable = {}
            if (isString(summary)) {
                parseSummaryTitle(summary as string, showColumns, config)
            }
            const showColumnNames = showColumns.value.map(v => v.key)
            summaryColumns.value.forEach(column => parseColumn(column, showColumnNames, tableData, config))
            return config
        }
    }

    /**
     * 是否需要统计
     */
    const hasSummary = computed(() => {
        return unref(summaryColumns).length > 0 || unref(props).summary
    })

    /**
     * 解释统计标题
     */
    const parseSummaryTitle = (column: string | GetanTableSummaryTitleProps, showColumns: Ref<Recordable[]>, result: Recordable) => {
        if (isString(column)) {
            const index = unref(props).useIndex ? 1 : 0
            result[showColumns.value[index].key] = {
                value: h("span", { style: { color: "red" } }, column as string)
            }
        } else if (isObject(column)) {
            const config = column as GetanTableSummaryTitleProps
            const ps: Recordable = {
                value: h("span", { style: { color: "red" } }, config.title)
            }
            if (config.colSpan) {
                ps.colSpan = config.colSpan
            }
            result[config.refColumn] = ps
        }
    }

    /**
     * 解释列配置中的统计
     */
    const parseColumn = (column: GetanTableColumnProps, names: string[], tableData: Recordable[], result: Recordable) => {
        if (names.includes(column.property)) {
            const { property, summary } = column
            if (isString(summary)) {
                const summaryStr = summary as string
                if (["AVG", "SUM"].includes(summaryStr)) {
                    result[property] = {
                        value: h("span", { style: { color: "red" } }, parseSummaryFunction(property, summaryStr as SummaryFunction, tableData))
                    }
                } else {
                    result[property] = {
                        value: h("span", { style: { color: "red" } }, summaryData.value[summaryStr])
                    }
                }
            } else if (isObject(summary)) {
                const summaryObj = { ...(summary as object), property } as GetanTableSummaryColumnProps
                parseSummaryColumn(summaryObj, tableData, result)
            }
        }
    }

    const parseSummaryFunction = (columnProperty: string, summaryFunction: SummaryFunction, tableData: Recordable[]) => {
        switch (summaryFunction) {
            case "SUM":
                return tableData.reduce((total, current) => total + current[columnProperty], 0)
            case "AVG":
                const result = tableData.reduce((total, current) => total + current[columnProperty], 0)
                return result / tableData.length
            default:
                return () => 0
        }
    }

    const parseSummaryColumn = (column: GetanTableSummaryColumnProps, tableData: Recordable[], result: Recordable) => {
        const { refColumn, render, property } = column
        const ps: Recordable = {}
        if (isFunction(render)) {
            ps.value = (render as Function)(tableData, summaryData)
        } else if (property) {
            ps.value = h("span", { style: { color: "red" } }, summaryData.value[property])
        } else if (column.function) {
            ps.value = h("span", { style: { color: "red" } }, parseSummaryFunction(refColumn, column.function, tableData))
        }
        if (column.colSpan) {
            ps.colSpan = column.colSpan
        }
        result[refColumn] = ps
    }

    const parseSummary = (summaryProps: GetanTableSummaryProps, tableData: Recordable[], showColumns: Ref<Recordable[]>) => {
        const { title, columns = [] } = summaryProps
        const result: Recordable = {}
        if (title) {
            parseSummaryTitle(title, showColumns, result)
        }
        const showColumnNames = showColumns.value.map(v => v.key)
        columns.forEach(column => {
            if (isString(column)) {
                const columnStr = column as string
                if (showColumnNames.includes(columnStr)) {
                    result[columnStr] = {
                        value: h("span", { style: { color: "red" } }, summaryData.value[columnStr])
                    }
                }
            } else if (isObject(column)) {
                const columnObj = column as GetanTableSummaryColumnProps
                if (showColumnNames.includes(columnObj.refColumn)) {
                    parseSummaryColumn(columnObj, tableData, result)
                }
            }
        })
        return result
    }

    const setSummaryData = (data: Recordable) => {
        summaryData.value = data
    }

    return { setSummaryData, summary: summaryFunction, hasSummary }
}
